# -*- coding: utf-8 -*-

"""
  @author: tangliqi
  @date: 2022/11/17 11:40
  @python version: 3.6 
  @contact me: 110
  ---------------------------------------
  @desc: python设计模式实现 => 装饰器模式.py
"""
from abc import ABC, ABCMeta, abstractmethod

# 代理模式与装饰器模式在设计意图和目的上有一定的区别，在代码结构上非常相似甚至可以一样
""" 
对于添加缓存这个应用场景使用哪种模式，要看设计者的意图，如果设计者不需要用户关注是否使用缓存功能，要隐藏实现细节，
也就是说用户只能看到和使用代理类，那么就使用proxy模式；
反之，如果设计者需要用户自己决定是否使用缓存的功能，
需要用户自己新建原始对象并动态添加缓存功能，那么就使用decorator模式。

Decorator关注为对象动态的添加功能, Proxy关注对象的信息隐藏及访问控制。
Decorator体现多态性, Proxy体现封装性。
"""


# 通过一个输出日志的例子来说明装饰器类
# 日志可以记录多种信息，基本的日志可以输出日志内容
# 可以通过增强功能，给日志添加输出时间、保存到文件、保存到数据库等功能。
# 装饰器模式主要需要实现三种类 1.抽象类（主要实现抽象接口）2.原始类（被装饰的类，继承抽象类）3.装饰器类（用于装饰原始类增强功能，继承自抽象装饰类

# 装饰器模式在 python 中，有更优雅和高效的实现方式，具体可以看 python装饰器 的实现：https://blog.csdn.net/tlqwanttolearnit/article/details/127573195

# ============================  抽象类  ============================
class LogABC:
    @abstractmethod
    def error(self):
        pass


class LogDeco(LogABC):

    def error(self):
        pass


# ============================  原始类  ============================
class Log(LogABC):

    def error(self):
        print("log输出日志...")


# ============================  装饰器类  ============================
class TimeLog(LogDeco):
    """增加日志输出时间"""

    def __init__(self, log: LogABC):
        self.log = log

    def error(self):
        print("打印当前时间")
        self.log.error()


class LevelLog(LogDeco):
    """增加日志输出级别"""

    def __init__(self, log: LogABC, level):
        self.log = log
        self.level = level

    def error(self):
        print("日志级别为:{}".format(self.level))
        self.log.error()


if __name__ == '__main__':
    # 未增强装饰，直接使用
    log = Log()
    log.error()

    print("===== 装饰输出时间 =====")
    time_log = TimeLog(log)
    time_log.error()

    print("=====多重装饰 =====")
    level_log = LevelLog(time_log, level="info")
    level_log.error()
